home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
asmcode.lbr
/
SCRNSAVE.AQM
/
SCRNSAVE.ASM
Wrap
Assembly Source File
|
1985-06-03
|
8KB
|
267 lines
PAGE ,132
;
; Screen erase program - by Bob Murphy 9/16/84
;
; This program will erase the display after the specified number of minutes.
; Any Video I/O or Keyboard I/O will cause a restore of the display.
;
;
; FORMAT:
;
; SCRNSAVE [NN]
;
; WHERE NN IS A 1 OR 2 DIGIT NUMBER OF MINUTES BETWEEN 1 AND 29.
; THE DEFAULT VALUE IS 5 MINUTES.
;
;
;
; DEFINE THE CODE SEGMENT, AND SET THINGS UP FOR A .COM PROGRAM
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG, DS:CSEG
ORG 100H
START: JMP INIT000 ;JUMP AROUND THE DATA AREA
;
; EQUATES
;
ADDR_6845 EQU 63H ; CRT CONTROL PORT BASE ADDRESS
CRT_MODE_SET EQU 65H ; CURRENT STATE OF CRT MODE REGISTER
;
; MISC DATA FIELDS
;
INITFLAG DB 0 ;USED TO DETERMINE IF WE SHOULD STAY RES
SWFLAG DB 0 ;VIDEO NOT SWITHCED OFF (1 IF WE DID)
COUNT DW 0 ;TIMER COUNT
DELAY DW 0 ;COUNT FOR TIME-OUT
PGM_ID DB 'SCRNSAVE' ;THIS MUST BE AFTER CRTJMP!
PGM_IDL EQU $-PGM_ID ;COMPARE LENGTH
PAGE
;
; INTERRUPT VECTOR CONTROL BLOCKS. ALL 3 MUST BE IDENTICAL
;
; TIMER TICK INTERRUPT TABLE
;
TIMER LABEL DWORD ;ADDRESS OF REAL TIMER INT
TIMEOFF DW 0
TIMESEG DW 0
TIMEADDR DW TIMETICK ;OFFSET OF NEW TIMER INTERRUPT
TIMEINT DB 1CH ;TIMER INTERRUPT NUMBER
DB 0 ;SPARE
INTBLK EQU $-TIMER ;LENGTH OF AN INTERRUPT CONTROL BLOCK
;
; KEY STRIKE INTERRUPT TABLE
;
KEY LABEL DWORD ;ADDRESS OF REAL KEYBOARD INT
DW 0
DW 0
DW KEY_IN ;OFFSET OF NEW KB INTERRUPT
DB 09H ;KB INTERRUPT ADDRESS
DB 0 ;SPARE
;
; CRT OUTPUT INTERRUPT TABLE
;
CRT LABEL DWORD ;ADDRESS OF REAL VIDEO INT (INT 10H)
DW 0
DW 0
DW CRTOUT ;OFFSET OF NEW TIMER INTERRUPT
DB 10H ;VIDEO INTERRUPT NUMBER
DB 0 ;SPARE
PAGE
;
;PROCESS THE 1CH INTERRUPT WHICH OCCURS 18.2 TIMES PER SECOND
;
TIMETICK:
STI ;RESTORE INTERRUPTS
PUSH AX ;SAVE SOME REGISTERS
PUSH DS
MOV AX,CS
MOV DS,AX ;SET THE DS REGISTER SAME AS CS
MOV AX,COUNT
INC AX
MOV COUNT,AX ;INCREMENT THE VALUE
CMP AX,DELAY ;UNTIL WE GET TO SELECTED DELAY
;THIS VALUE IS 444H PER MINUTE
JL TIME800 ;LESS THAN DELAY TIME - SKIP TURN OFF
;
; SHUT OFF VIDEO OPERATION
;
PUSH DX ;SAVE THESE REGISTERS, TOO
PUSH ES
MOV AX,0040H ;BIOS DATA AREA BASE
MOV ES,AX
MOV DX,ES:ADDR_6845 ;GET BASE ADDRESS OF THE VIDEO CONTROLLER
ADD DX,4 ;POINT TO CONTROLLER'S MODE REGISTER
MOV AL,ES:CRT_MODE_SET ;GET CURRENT MODE SETTINGS
AND AL,11110111B ;CLEAR THE VIDEO ENABLE BIT TO
OUT DX,AL ;TURN OFF THE VIDEO.
POP ES
POP DX
MOV SWFLAG,1 ;FLAG THAT WE HAVE SWITCHED OFF
;
; GO TO THE STANDARD TIMER INTERRUPT
;
TIME800:
POP DS ;STANDARD EXIT. RESTORE USED REGISTERS
POP AX ;AND PROCESS WHATEVER WAS AT INT 1CH
PUSHF ;BEFORE THIS PROGRAM CAME INTO ACTION.
CALL CS:TIMER ;PUSH DUMMY FLAGS, AND FAKE AN INT 1CH
IRET
PAGE
;
; THE USER HAS PRESSED A KEY...
;
KEY_IN:
STI ;RESTORE INTERRUPTS
CALL CHKSCRN ;IF SCREEN OFF - TURN IT BACK ON
PUSHF ;DUMMY PUSH TO FAKE AN INT INSTRUCTION
CALL CS:KEY ;GO TO REAL KEYBOARD ROUTINE
IRET ;AND RETURN TO WHAT WAS RUNNING BEFORE
;
;THE SYSTEM WANTS TO OUTPUT TO THE SCREEN...
;
CRTOUT:
STI ;RESTORE INTERRUPTS
CALL CHKSCRN ;IF CRT IS OFF-TURN IT BACK ON
PUSHF ;FAKE AN INT 10H
CALL CS:CRT ;PROCESS THE VIDEO REQUEST
IRET ;GO BACK TO CALLING PROGRAM
;
; A KEY HAS BEEN PRESSED OR CRT WRITE ATTEMPTED - TURN SCREEN BACK ON
;
CHKSCRN PROC NEAR
CMP CS:SWFLAG,0 ;HAVE WE SWITCHED THE VIDEO OFF?
JE CHKS400 ;NO-SKIP
PUSH AX ;SAVE REGISTERS
PUSH DS
PUSH DX
PUSH ES
MOV AX,CS
MOV DS,AX ;SET THE DS REGISTER SAME AS CS
MOV AX,0040H ;FIRST, POINT TO THE ROM DATA AREA
MOV ES,AX
MOV DX,ES:ADDR_6845 ;GET BASE ADDRESS OF VIDEO CONTROLLER
ADD DX,4 ;AND POINT TO CONTROLLER MODE REGISTER
MOV AL,ES:CRT_MODE_SET ;GET THE OLD MODE SETTINGS AND
OUT DX,AL ;RESTORE THEM.
MOV SWFLAG,0 ;NOT SWITCHED OFF ANYMORE
POP ES
POP DX
POP DS ;RESTORE REGISTERS
POP AX
CHKS400:
MOV CS:COUNT,0 ;RESET (AGAIN) COUNT TO 0
RET
CHKSCRN ENDP
;
END_PR: ;USED TO DETERMINE LENGTH OF PROGRAM
PAGE
ERR1MSG DB 'PARM MUST BE A NUMBER BETWEEN 1 AND 29',7,13,10,'$'
GOODMSG DB 13,10,'SCREEN SAVER INITIALIZED',13,10,'$'
RESTMSG DB 13,10,'SCREEN SAVER TIME RESET',13,10,'$'
;
; INITIALIZATION CODE - DOES NOT STAY RESIDENT
;
INIT000: MOV AX,5 ;DEFAULT TIME VALUE
MOV SI,80H ;SEE IF ANY INPUT DATA
MOV CL,[SI] ;GET CHARACTER COUNT
SUB CH,CH
OR CL,CL ;ANYTHING INPUT?
JZ INIT100 ;NO-USE DEFAULT 5 MINUTE DELAY
MOV DL,10 ;MULTIPLY VALUE
SUB AX,AX ;VALUE ACCUMULATION REGISTER
SUB BH,BH ;HI SIDE OF PICKUP REG = 0 FOR ADD
INIT020: INC SI ;POINT TO CHARACTER
MOV BL,[SI]
CMP BL,' ' ;BLANK?
JE INIT040 ;YES-DISCARD IT
CMP BL,'0' ;CHK FOR DIGIT
JL INIT900 ;INVALID - THEN ERR1
CMP BL,'9' ;SAME THING
JG INIT900 ;FALL THRU ON A VALID DIGIT
SUB BL,'0' ;SET RANGE 0-9
MUL DL
ADD AX,BX ;SUM DIGITS
CMP AX,29 ;EXCEED MAX TIME OF 29 MINUTES?
JG INIT900 ;YES-ERROR
INIT040: LOOP INIT020 ;DO NEXT DIGIT
OR AX,AX ;ZERO TIME?
JZ INIT900 ;YES-INVALID TIME
PAGE
;
; AX CONTAINS A VALID TIME PERIOD (0 < AX < 30). SEE IF PGM LOADED BEFORE
;
; CRT VECTOR SELECTED, BECAUSE ITS THE LEAST LIKELY TO BE MODIFIED BY A
; SUBSEQUENT PROGRAM. (WHO WOULD WANT TO TRAP THE VIDEO ROUTINE?)
;
INIT100: PUSH AX
MOV AH,35H ;GET VECTOR COMMAND
MOV AL,10H ;FOR CRT
INT 21H ;POINT TO CRT VECTOR W/ES:BX
; ;IF PGM LOADED BEFORE, ES IS THE BASE
MOV CX,PGM_IDL ;COMPARE LENGTH
MOV SI,OFFSET PGM_ID ;POINT TO THIS PROGRAM ID
MOV DI,SI
REP CMPSB ;SEE IF PROGRAM ID MATCH OCCURS
JNE INIT200 ;IF DIFFERENT, WE WANT TO STAY RESIDENT
MOV INITFLAG,1 ;SET DONT STAY RESIDENT
PUSH ES ;ES HAS BASE OF RESIDENT VERSION
POP DS ;USE DELAY FIELD IN RESIDENT COPY
INIT200: POP AX ;RESTORE TIME COUNT
MOV BX,444H ;TICKS PER MINUTE
MUL BX ;CONVERT MINUTES TO TICKS
MOV DELAY,AX ;SAVE DELAY TIME PERIOD
PUSH CS
POP DS ;SEE THAT WERE USING OUR OWN PROGRAM
CMP INITFLAG,0 ;ARE WE GOING TO STAY RESIDENT?
JNZ INIT940 ;NO-THEN VECTORS ALREADY SET
PAGE
;
; INITIALIZE TIMER, KEYBOARD, AND CRT VECTORS
;
SUB SI,SI ;START INITIALIZATION WITH TIMER INT
MOV CX,3 ; 3 INTS TO INITIALIZE
SUB AX,AX
MOV ES,AX ;ADDRESS LOW CORE
INIT400: CALL SETVEC ;INITIALIZE 1 INTERRUPT VECTOR
ADD SI,INTBLK ;INDEX TO NEXT BLOCK
LOOP INIT400 ;DO ALL 3
MOV DX,OFFSET GOODMSG
MOV AH,9
INT 21H ;SEND MESSAGE
MOV DX,OFFSET END_PR ;POINT TO END OF RESIDENT CODE
INT 27H ;TERM & STAY RESIDENT
;
;
INIT900: MOV DX,OFFSET ERR1MSG ;ERROR IN PARAMETER
JMP INIT980
INIT940: MOV DX,OFFSET RESTMSG ;PGM RESIDENT ALREADY-TIME RESET
JMP INIT980
INIT980: MOV AH,9
INT 21H ;SEND MESSAGE
INT 20H ;ABORT
;
; SET UP AN INTERRUPT VECTOR FROM VECTOR ASSIGNMENT TABLE
;
SETVEC PROC NEAR
MOV AL,TIMEINT [SI] ;GET INTERRUPT ADDRESS TO MODIFY
MOV AH,35H ;GET GET VECTOR DOS CALL
INT 21H ;RETURN VECTOR IN ES:BX
MOV TIMEOFF [SI],BX ;SAVE ORIGINAL VECTOR OFFSET
MOV BX,ES ;GET SEGMENT
MOV TIMESEG [SI],BX ;SAVE ORIGINAL VECTOR SEGMENT
MOV DX,TIMEADDR [SI] ;GET REPLACEMENT INTERRUPT VECTOR OFFSET
MOV AH,25H ;SET UP NEW VECTOR FOR TIMER ETC
INT 21H ;HAVE DOS DO THIS FOR US
RET ;ALL DONE WITH THIS VECTOR
SETVEC ENDP
CSEG ENDS
END START